package com.hualala.supplychain.methodext;

import com.alibaba.fastjson.JSON;
import com.hualala.supplychain.methodext.annotation.DoMethodExtAround;
import com.hualala.supplychain.methodext.utils.ResultUtils;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.joor.Reflect;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Log4j2
public class DoMethodExtAroundPoint {

    @Autowired
    private ApplicationContext applicationContext;


    @Pointcut("@annotation(com.hualala.supplychain.methodext.annotation.DoMethodExtAround)")
    public void aopPoint() {
    }

    @Around("aopPoint()  && @annotation(doMethodExtAround)")
    public Object doRouter(ProceedingJoinPoint jp, DoMethodExtAround doMethodExtAround) throws Throwable {
        // 获取内容
        Method method = getMethod(jp);
        // 功能处理
        Reflect on = Reflect.on(applicationContext.getBean(doMethodExtAround.className()));
        String returnType = on.type().getMethod(doMethodExtAround.method(), method.getParameterTypes()).getReturnType().getName();
        if(!returnType.equals("boolean")){
            throw new Exception("入口切点返回类型必须为boolean类型！");
        }
        Boolean flag = on.call(doMethodExtAround.method(), jp.getArgs()).get();
        return flag ? jp.proceed() : ResultUtils.getFail("001", doMethodExtAround.returnJson());
    }

    public Method getMethod(JoinPoint jp) throws Exception {
        Signature sig = jp.getSignature();
        MethodSignature methodSignature = (MethodSignature) sig;
        //return Reflect.on(this.applicationContext.getBean(jp.getTarget().getClass())).type().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        return jp.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
    }

}
